﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Net;
using System.Text;
using System.Xml;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using System.Security.Principal;
using System.ServiceProcess;


namespace UpdateApp
{
    public class Param { 
        public bool Result {get;set;}
        public string Url {get;set;}
        public string ReStartList { get; set; }
        public string ReStartServiceList { get; set; }
        public string PackName { get; set; }
        public string KillList { get; set; }
        public string KillServiceList { get; set; }
        public bool RequiredUpdate {get;set;}
    }
    public class Update
    {
        WebClient _client;
        public Update()
        {
            _client = new WebClient();
            _client.DownloadFileCompleted += (sender, args) => { if( DownloadFileCompleted!=null)DownloadFileCompleted.Invoke(sender, args); };
            _client.DownloadProgressChanged += (sender, args) => { if( DownloadProgressChanged!=null)DownloadProgressChanged.Invoke(sender, args); };
        }
        public delegate void MyAction(object obj,object args);
        /// <summary>
        /// 在异步文件下载操作完成时发生。
        /// </summary>
        public MyAction DownloadFileCompleted { get; set; }
        /// <summary>
        /// 在异步下载操作成功转换部分或全部数据后发生
        /// </summary>
        public MyAction DownloadProgressChanged { get; set; }
        /// <summary>
        /// 根据名字 关闭进程
        /// </summary>
        /// <param name="ProcessName"></param>
        /// <returns></returns>
        public static bool CloseProcess(string ProcessName)
        {
            bool result = false;
            var temp = System.Diagnostics.Process.GetProcessesByName(ProcessName);
            foreach (var item in temp)
            {
                try
                {
                    item.Kill();
                    result = true;
                }
                catch
                {
                }
            }
            return result;
        }
        /// <summary>
        /// 停止服务
        /// </summary>
        /// <param name="ServiceName"></param>
        public static void StopService(string ServiceName)
        {
            using (ServiceController Ctr = new ServiceController(ServiceName))
            {
                try{
                if (Ctr.Status == ServiceControllerStatus.Running)
                    Ctr.Stop();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }
        /// <summary>
        /// 启动服务
        /// </summary>
        /// <param name="ServiceName"></param>
        public static void StartService(string ServiceName)
        {
            using (ServiceController Ctr = new ServiceController(ServiceName))
            {
                try
                {
                    if (Ctr.Status == ServiceControllerStatus.Stopped || Ctr.Status == ServiceControllerStatus.Paused)
                        Ctr.Start();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }
        public static ServiceControllerStatus ServiceStatus(string ServiceName)
        {
            ServiceControllerStatus temp = 0;
            using (ServiceController Ctr = new ServiceController(ServiceName))
            {
                temp = Ctr.Status;
            }
            return temp;
        }
        public static bool ServiceExists(string ServiceName)
        {
            foreach (var s in ServiceController.GetServices())
            {
                if (s.ServiceName.ToLower().Equals(ServiceName.ToLower()))
                {
                    return true;
                }
            }
            return false;
        }
        /// <summary>
        /// 检查是否有新版本
        /// </summary>
        /// <returns></returns>
        public static Param HasNewVersion()
        {
            try
            {
                var appPath = Directory.GetParent(Application.StartupPath).FullName;
                var localxdoc = new XmlDocument();
                localxdoc.Load(appPath + "\\LocalVersion.xml");
                var localV = localxdoc.GetElementsByTagName("version")[0].InnerText;
                var localU = localxdoc.GetElementsByTagName("url")[0].InnerText;
                //更新完成后需要启动的应用程序名称
                var reStartList = localxdoc.GetElementsByTagName("reStartList")[0].InnerText;
                //更新完成后需要启动的服务名称
                var reStartServiceList = localxdoc.GetElementsByTagName("reStartServiceList")[0].InnerText;

                //更新过程必须关掉的进程列表
                var localKillList = localxdoc.GetElementsByTagName("killList")[0].InnerText;
                //更新过程必须关掉的服务列表
                var localKillServiceList = localxdoc.GetElementsByTagName("killServiceList")[0].InnerText;

                var serverxdoc = new XmlDocument();
                serverxdoc.Load(localU);
                //服务端版本
                var serverV = serverxdoc.GetElementsByTagName("version")[0].InnerText;
                //更新包地址
                var serverU = serverxdoc.GetElementsByTagName("url")[0].InnerText;
                //是否必须更新
                var serverRU = serverxdoc.GetElementsByTagName("requiredUpdate")[0].InnerText;

                var temp2 = Convert.ToInt32(serverV.Replace(".", ""));
                var temp3 = Convert.ToInt32(localV.Replace(".", ""));

                return new Param
                {
                    Result = temp2 > temp3,
                    Url = serverU,
                    ReStartList = reStartList,
                    ReStartServiceList = reStartServiceList,
                    PackName = Path.GetFileNameWithoutExtension(serverU),
                    KillList = localKillList,
                    RequiredUpdate = Convert.ToBoolean(serverRU),
                    KillServiceList = localKillServiceList
                };
            }
            catch{
                return new Param { Result = false };
            }                      
        }
        /// <summary>
        /// 异步下载文件
        /// </summary>
        /// <param name="param"></param>
        public void Download(Param param)
        {
            var savePath = AppDomain.CurrentDomain.BaseDirectory;
            var downUrl = param.Url;
            _client.DownloadFileAsync(new Uri(downUrl), savePath + param.PackName + ".zip", param);
        }

        /// <summary>
        /// 判断本程序当前是否运行在系统盘
        /// </summary>
        /// <returns></returns>
        public static bool IsSystemPath()
        {
            //系统盘路径
            string path = Environment.GetEnvironmentVariable("systemdrive");
            return Application.StartupPath.StartsWith(path, StringComparison.OrdinalIgnoreCase);
        }
        /// <summary>
        /// 判断本程序当前是否以管理员身份运行
        /// </summary>
        /// <returns></returns>
        public static bool IsAdministrator()
        {
            WindowsIdentity current = WindowsIdentity.GetCurrent();
            WindowsPrincipal windowsPrincipal = new WindowsPrincipal(current);
            return windowsPrincipal.IsInRole(WindowsBuiltInRole.Administrator);
        }
        /// <summary>
        /// 以管理员身份重新启动程序
        /// </summary>
        public static void ReStartAppWithAdministrator()
        {
            try
            {
                System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
                startInfo.UseShellExecute = true;
                //startInfo.WorkingDirectory = $@"{AppDomain.CurrentDomain.BaseDirectory}";
                startInfo.FileName = string.Format(@"{0}\{1}.exe", Application.StartupPath, Process.GetCurrentProcess().ProcessName);
                //设置启动动作,确保以管理员身份运行
                startInfo.Verb = "runas";
                System.Diagnostics.Process.Start(startInfo);
            }
            catch
            {

            }
        }
    }
}
